package com.dkd.system.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;

import com.dkd.system.domain.NewTemplateVo;
import com.dkd.system.domain.TCodeRule;
import com.dkd.system.domain.TTemplate;
import com.dkd.system.mapper.TCodeRuleMapper;
import com.dkd.system.mapper.TTemplateMapper;
import com.dkd.system.utils.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.dkd.common.annotation.Log;
import com.dkd.common.core.controller.BaseController;
import com.dkd.common.core.domain.AjaxResult;
import com.dkd.common.enums.BusinessType;
import com.dkd.system.domain.TWarranty;
import com.dkd.system.service.ITWarrantyService;
import com.dkd.common.utils.poi.ExcelUtil;
import com.dkd.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * listController
 * 
 * @author chuyongshuo
 * @date 2025-08-07
 */
@RestController
@RequestMapping("/warranty/booklist")
public class TBookListController extends BaseController
{
    @Autowired
    private ITWarrantyService tWarrantyService;

    @Autowired
    private TCodeRuleMapper codeRuleMapper;

    @Autowired
    private TTemplateMapper tTemplateMapper;


    @Value("${ruoyi.template.json.storage-path}")
    private String storagePath; // 在application.yml中配置存储路径，如: D:/template-json/


//    private String qrcodeUrl ="http://www.zbs.zhejiangdalong.com:81/details/"; //生产环境
    private String qrcodeUrl ="http://www.dev.zbs.zhejiangdalong.com/details/"; //测试环境
    /**
     * 复制质保书
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:add')")
    @Log(title = "质保书列表", businessType = BusinessType.INSERT)
    @PostMapping("/copy")
    public AjaxResult copyWarranty(@RequestBody TWarranty tWarranty) {
        System.out.println("tWarranty = " + tWarranty);
        try {
            // 1. 生成质保书编号
            TCodeRule codeRule = codeRuleMapper.selectTCodeRuleOneByStatus();
            if (codeRule == null) {
                return AjaxResult.error("编码规则未配置");
            }

            int nextSeq = CodeGenerator.getNextSequence(
                    codeRule.getCurrentValue(),
                    codeRule.getSeqLength(),
                    codeRule.getResetType(),
                    new Date()
            );

            String code = CodeGenerator.generateCode(
                    codeRule.getPrefix(),
                    codeRule.getDateFormat(),
                    codeRule.getSeqLength(),
                    nextSeq
            );

            // 更新编码规则
            codeRule.setCurrentValue(nextSeq);
            codeRule.setUpdateAt(new Date());
            if (codeRuleMapper.updateTCodeRule(codeRule) != 1) {
                return AjaxResult.error("编码规则更新失败");
            }

            Integer copyId = tWarranty.getCopyId(); //获取到复制的质保书id
            TWarranty oldTWarranty = tWarrantyService.selectTWarrantyById(copyId);
            if (oldTWarranty==null){
                return AjaxResult.error("复制的质保书为空");
            }
            //修改这里
            // 2. 获取JSON模板路径后读取到数据进行占位符替换
            String jsonPath = getTemplateJsonData(tWarranty);
            if (jsonPath == null) {
                return AjaxResult.error("获取json路径失败");
            }
            String jsonData;
            try {
                jsonData = Files.readString(Paths.get(jsonPath), StandardCharsets.UTF_8);
            } catch (IOException e) {
                return AjaxResult.error("模板读取失败");
            }
            tWarranty.setId(null);
            tWarranty.setStatus(0); //更改状态为草稿
            tWarranty.setCertificateNo(code);
            tWarranty.setCreatedAt(new Date());
            tWarranty.setUpdatedAt(new Date());
            //根据数据库内容做替换
            Map<String, String> replacements = ReplaceBook.replacements(oldTWarranty, tWarranty);
            jsonData = ReplaceBook.replaceByJsonPath(jsonData, replacements);
            //4.先新增后获取到id
            tWarrantyService.insertTWarranty(tWarranty);
            Integer id1 = tWarranty.getId();
            String key = RandomKeyGenerator.generateRandomKey();
            Map<String, String> map = LuckySheetQRCodeReplacer.replaceImageWithQRCode(
                    jsonData,
                    1,
                    qrcodeUrl + id1+"-"+key
            );
            String updatedJson = map.get("json");
            String qrcodeBase64 = map.get("qrcode");
            String filename = "template_" + tWarranty.getTemplateId() + "_" + System.currentTimeMillis() + ".json";
            String jsonOutPath = StoragePathUtils.storeFileStream(storagePath, filename,
                    new ByteArrayInputStream(updatedJson.getBytes(StandardCharsets.UTF_8)));
            //5.替换二维码后根据id修改json串
            tWarranty.setSecret(key);
            tWarranty.setQrcodeLocation(qrcodeBase64);
            tWarranty.setJsonData(jsonOutPath);
            tWarrantyService.updateTWarranty(tWarranty);
            return AjaxResult.success("复制成功",id1);
        } catch (Exception e) {
            return AjaxResult.error("复制失败：" + e.getMessage());
        }
    }


    /**
     * 将JSON中的旧对象属性值替换为新对象属性值
     * @param jsonData JSON数据字符串
     * @param oldWarranty 旧对象（源数据）
     * @param newWarranty 新对象（目标数据）
     * @return 替换后的JSON字符串
     */
    private String replaceWarrantyProperties(String jsonData, TWarranty oldWarranty, TWarranty newWarranty) throws JsonProcessingException {

        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(jsonData);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");

        // 获取旧对象的格式化值
        String oldReportDate = oldWarranty.getReportDate() != null
                ? sdf.format(oldWarranty.getReportDate())
                : "";

        // 获取新对象的格式化值
        String newReportDate = newWarranty.getReportDate() != null
                ? sdf.format(newWarranty.getReportDate())
                : "";

        // 使用Map定义所有需要替换的映射（旧值 -> 新值）
        Map<String, String> replacements = new HashMap<>();

        // 客户名称
        if (oldWarranty.getCustomer() != null && newWarranty.getCustomer() != null) {
            replacements.put(oldWarranty.getCustomer(), newWarranty.getCustomer());
        }

        // 合同号
        if (oldWarranty.getContractNo() != null && newWarranty.getContractNo() != null) {
            logger.info("老的合同{}，新的合同{}",oldWarranty.getContractNo(), newWarranty.getContractNo());
            replacements.put(oldWarranty.getContractNo(), newWarranty.getContractNo());
        }

        // 材料名称
        if (oldWarranty.getSteelGrade() != null && newWarranty.getSteelGrade() != null) {
            replacements.put(oldWarranty.getSteelGrade(), newWarranty.getSteelGrade());
        }

        //炉号
        if (oldWarranty.getFurnaceNo() != null && newWarranty.getFurnaceNo() != null) {
            logger.info("老的炉号{}，新的炉号{}",oldWarranty.getFurnaceNo(), newWarranty.getFurnaceNo());
                replacements.put(oldWarranty.getFurnaceNo(), newWarranty.getFurnaceNo());
        }

        // 产品类别
        if (oldWarranty.getProductCategory() != null && newWarranty.getProductCategory() != null) {
            replacements.put(oldWarranty.getProductCategory(), newWarranty.getProductCategory());
        }

        // 报告日期
        if (!oldReportDate.isEmpty() && !newReportDate.isEmpty()) {
            replacements.put(oldReportDate, newReportDate);
        }

        // 证书编码
        if (oldWarranty.getCertificateNo() != null && newWarranty.getCertificateNo() != null) {
            replacements.put(oldWarranty.getCertificateNo(), newWarranty.getCertificateNo());
        }


        // 遍历并替换所有旧值为新值
        for (Map.Entry<String, String> entry : replacements.entrySet()) {
            System.out.println("entry = " + entry);
            if (!entry.getKey().isEmpty() && !entry.getValue().isEmpty()) {
                jsonData = jsonData.replace(entry.getKey(), entry.getValue());
            }
        }

        return jsonData;
    }


    /**
     * 将质保书另存为新模板
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:add')")
    @PostMapping(value = "/newTemplate")
    public AjaxResult newTemplate(@RequestBody NewTemplateVo newTemplateVo) throws IOException {
        NewTemplateVo templateVo = newTemplateVo;
        System.out.println("templateVo = " + templateVo);
        Integer bookId = templateVo.getBookId(); //获取质保书id
        TWarranty tWarranty = tWarrantyService.selectTWarrantyById(bookId);
        System.out.println("tWarranty = " + tWarranty);
        TTemplate templateCopy = tTemplateMapper.selectTTemplateById(tWarranty.getTemplateId());
        System.out.println("templateCopy = " + templateCopy);
        //获取excel路径
        String jsonPath = tWarranty.getJsonData();//路径
        System.out.println("jsonPath = " + jsonPath);
        String filename = "template_" + tWarranty.getTemplateId() + "_" + System.currentTimeMillis() + ".json";
        String jsonData;
        try {
            jsonData = Files.readString(Paths.get(jsonPath), StandardCharsets.UTF_8);
        } catch (IOException e) {
            return AjaxResult.error("质保书JSON文件读取失败");
        }
        //反向替换
        jsonData = restorePlaceholders(jsonData, tWarranty);
        String jsonOutPath = StoragePathUtils.storeFileStream(storagePath, filename,
                new ByteArrayInputStream(jsonData.getBytes(StandardCharsets.UTF_8)));
        System.out.println("jsonOutPath = " + jsonOutPath);
        TTemplate tTemplate = new TTemplate();
        tTemplate.setTemplateName(newTemplateVo.getTemplateName()); //模板名称
        tTemplate.setDescribe(newTemplateVo.getDescribe());//模板描述
        if (newTemplateVo.getQrcodeLocation()==null || "".equals(newTemplateVo.getQrcodeLocation())){
            //如果赋值质保书表头为空，那么使用原来模板锁定表头字段
            tTemplate.setQrcodeLocation(templateCopy.getQrcodeLocation()); //表头锁定
        }else {
            tTemplate.setQrcodeLocation(newTemplateVo.getQrcodeLocation());
        }

        tTemplate.setCreatedAt(new Date());
        tTemplate.setUpdatedAt(new Date());
        tTemplate.setJsonData(jsonOutPath);
        tTemplate.setFileLocation(templateCopy.getFileLocation());
        tTemplateMapper.insertTTemplate(tTemplate);
        return success(tTemplate);
    }

    /**
     * 将JSON中的实际值反向替换为占位符
     */
    private String restorePlaceholders(String jsonData, TWarranty tWarranty) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        String reportDate = tWarranty.getReportDate() != null
                ? sdf.format(tWarranty.getReportDate())
                : "";

        // 使用Map定义所有需要恢复的占位符映射（实际值 -> 占位符）
        Map<String, String> restorations = new HashMap<>();
        restorations.put(tWarranty.getCustomer() != null ? tWarranty.getCustomer() : "", "{customer}");//客户名称
        restorations.put(tWarranty.getContractNo() != null ? tWarranty.getContractNo() : "", "{contractNo}");//合同号
        restorations.put(tWarranty.getSteelGrade() != null ? tWarranty.getSteelGrade() : "", "{steelGrade}");//材料名称
        restorations.put(tWarranty.getProductCategory() != null ? tWarranty.getProductCategory() : "", "{productCategory}"); //产品类别
        restorations.put(tWarranty.getFurnaceNo() != null ? tWarranty.getFurnaceNo() : "", "{furnaceNo}"); //炉号
        restorations.put(tWarranty.getQuantity() != null ? tWarranty.getQuantity() : "", "{quantity}"); //规格数量
        restorations.put(reportDate, "{reportDate}");//报告日期
        restorations.put(tWarranty.getCertificateNo() != null ? tWarranty.getCertificateNo() : "","{certificateNo}");//证书编码

        // 遍历并替换所有实际值为占位符
//        for (Map.Entry<String, String> entry : restorations.entrySet()) {
//            if (!entry.getKey().isEmpty()) {
//                jsonData = jsonData.replace(entry.getKey(), entry.getValue());
//            }
//        }
        //修复logo替换
        jsonData = ReplaceBook.replaceByJsonPath(jsonData, restorations);

        return jsonData;
    }
    /**
     * 查询list列表
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:list')")
    @GetMapping("/list")
    public TableDataInfo list(TWarranty tWarranty)
    {
        startPage();
        List<TWarranty> list = tWarrantyService.selectTWarrantyList(tWarranty);
        return getDataTable(list);
    }

    /**
     * 导出list列表
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:export')")
    @Log(title = "质保书列表", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, TWarranty tWarranty)
    {
        List<TWarranty> list = tWarrantyService.selectTWarrantyList(tWarranty);
        ExcelUtil<TWarranty> util = new ExcelUtil<TWarranty>(TWarranty.class);
        util.exportExcel(response, list, "list数据");
    }

    /**
     * 获取list详细信息
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Integer id)
    {
        TWarranty tWarranty = tWarrantyService.selectTWarrantyById(id);
        return success(tWarranty);
    }

    /**
     * 新增质保书列表
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:add')")
    @Log(title = "质保书列表", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TWarranty tWarranty) {
        System.out.println("tWarranty = " + tWarranty);
        try {
            // 1. 生成质保书编号
            TCodeRule codeRule = codeRuleMapper.selectTCodeRuleOneByStatus();
            if (codeRule == null) {
                return AjaxResult.error("编码规则未配置");
            }

            int nextSeq = CodeGenerator.getNextSequence(
                    codeRule.getCurrentValue(),
                    codeRule.getSeqLength(),
                    codeRule.getResetType(),
                    new Date()
            );

            String code = CodeGenerator.generateCode(
                    codeRule.getPrefix(),
                    codeRule.getDateFormat(),
                    codeRule.getSeqLength(),
                    nextSeq
            );

            // 更新编码规则
            codeRule.setCurrentValue(nextSeq);
            codeRule.setUpdateAt(new Date());
            if (codeRuleMapper.updateTCodeRule(codeRule) != 1) {
                return AjaxResult.error("编码规则更新失败");
            }

            //修改这里
            // 2. 获取JSON模板路径后读取到数据进行占位符替换
            String jsonPath = getTemplateJsonData(tWarranty);
            if (jsonPath == null) {
                return AjaxResult.error("获取json路径失败");
            }
            String jsonData;
            try {
                jsonData = Files.readString(Paths.get(jsonPath), StandardCharsets.UTF_8);
            } catch (IOException e) {
                return AjaxResult.error("模板读取失败");
            }

            //根据jsonData路径读取文件内容
            //调用  // 3.2 新增模式：使用工具类生成带目录的文件路径
            // 3. 替换JSON中的占位符
            jsonData = replacePlaceholders(jsonData, tWarranty, code);
            tWarranty.setStatus(0); //更改状态为草稿
            tWarranty.setCertificateNo(code);
            tWarranty.setCreatedAt(new Date());
            tWarranty.setUpdatedAt(new Date());
            //4.先新增后获取到id
            tWarrantyService.insertTWarranty(tWarranty);
            Integer id1 = tWarranty.getId();
            String key = RandomKeyGenerator.generateRandomKey();
            Map<String, String> map = LuckySheetQRCodeReplacer.replaceImageWithQRCode(
                    jsonData,
                    1,
                    qrcodeUrl + id1+"-"+key
            );
            String updatedJson = map.get("json");
            String qrcodeBase64 = map.get("qrcode");
            String filename = "template_" + tWarranty.getTemplateId() + "_" + System.currentTimeMillis() + ".json";
            String jsonOutPath = StoragePathUtils.storeFileStream(storagePath, filename,
                    new ByteArrayInputStream(updatedJson.getBytes(StandardCharsets.UTF_8)));
            //5.替换二维码后根据id修改json串
            tWarranty.setSecret(key);
            tWarranty.setJsonData(jsonOutPath);
            tWarranty.setQrcodeLocation(qrcodeBase64);
            tWarrantyService.updateTWarranty(tWarranty);
            return AjaxResult.success("新增成功",id1);
        } catch (Exception e) {
            return AjaxResult.error("新增失败：" + e.getMessage());
        }
    }

    /**
     * 获取模板JSON数据
     */
    private String getTemplateJsonData(TWarranty tWarranty) {
        if (tWarranty.getCopyId() != null) {
            TWarranty warranty = tWarrantyService.selectTWarrantyJsonById(tWarranty.getCopyId());
            return warranty != null ? warranty.getJsonData() : null;
        } else {
            TTemplate tTemplate = tTemplateMapper.selectTTemplateJsonById(tWarranty.getTemplateId());
            return tTemplate != null ? tTemplate.getJsonData() : null;
        }
    }

    /**
     * 替换JSON中的占位符
     */
    private String replacePlaceholders(String jsonData, TWarranty tWarranty, String code) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        String reportDate = tWarranty.getReportDate() != null
                ? sdf.format(tWarranty.getReportDate())
                : "";

        // 使用Map定义所有需要替换的占位符
        Map<String, String> replacements = new HashMap<>();
        replacements.put("\\{customer\\}", tWarranty.getCustomer() != null ? tWarranty.getCustomer() : "");//客户名称
        replacements.put("\\{contractNo\\}", tWarranty.getContractNo() != null ? tWarranty.getContractNo() : "");//合同号
        replacements.put("\\{steelGrade\\}", tWarranty.getSteelGrade() != null ? tWarranty.getSteelGrade() : "");//材料名称
        replacements.put("\\{productCategory\\}", tWarranty.getProductCategory() != null ? tWarranty.getProductCategory() : ""); //产品类别
        replacements.put("\\{furnaceNo\\}", tWarranty.getFurnaceNo() != null ? tWarranty.getFurnaceNo() : ""); //炉号
        replacements.put("\\{quantity\\}", tWarranty.getQuantity() != null ? tWarranty.getQuantity() : ""); //规格数量
        replacements.put("\\{reportDate\\}", reportDate);//报告日期
        replacements.put("\\{certificateNo\\}", code);//证书编码

        // 遍历并替换所有占位符
        for (Map.Entry<String, String> entry : replacements.entrySet()) {
            jsonData = jsonData.replaceAll(entry.getKey(), entry.getValue());
        }

        return jsonData;
    }


    //回显数据
    /**
     * 修改list
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:list')")
    @Log(title = "质保书列表", businessType = BusinessType.UPDATE)
    @GetMapping("/priview/{id}")
    public void getBookJsonById(@PathVariable("id") Integer id, HttpServletResponse response) {
        logger.info("质保书列表，进行编辑,id是{}", id);
        try {
            // 1. 查询模板数据
            TWarranty tWarranty = tWarrantyService.selectTWarrantyJsonById(id);
            if (tWarranty == null || tWarranty.getJsonData() == null) {
                response.sendError(HttpStatus.NOT_FOUND.value(), "模板不存在或没有JSON数据");
                return;
            }

            // 2. 读取文件内容
            Path filePath = Paths.get(tWarranty.getJsonData());
            if (!Files.exists(filePath)) {
                response.sendError(HttpStatus.NOT_FOUND.value(), "JSON文件不存在");
                return;
            }

            // 3. 设置响应头
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "inline; filename=template_" + id + ".json");

            // 4. 文件流式传输
            Files.copy(filePath, response.getOutputStream());

        } catch (IOException e) {
            logger.error("获取模板JSON数据失败", e);
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        }
    }

    @PostMapping("/save")
    @PreAuthorize("@ss.hasPermi('warranty:booklist:add')")
    public AjaxResult saveJsonTemplate(
            @RequestPart("file") MultipartFile file,
            @RequestParam(value = "id", required = false) String id,
            @RequestParam(value = "updatedBy", required = false) String updatedBy) {

        try {
            // 1. 验证文件是否为空
            if (file.isEmpty()) {
                return AjaxResult.error("文件不能为空");
            }

            // 2. 读取并验证JSON（自动释放资源）
            String jsonContent;
            try (InputStream is = file.getInputStream()) {
                jsonContent = new String(is.readAllBytes(), StandardCharsets.UTF_8);
            }

            // 3. 验证是否为有效JSON
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode jsonNode = objectMapper.readTree(jsonContent);
            } catch (JsonProcessingException e) {
                return AjaxResult.error("无效的JSON格式");
            }
            TWarranty tWarranty = tWarrantyService.selectTWarrantyJsonById(Integer.valueOf(id));
            Files.write(
                    Paths.get(tWarranty.getJsonData()),
                    jsonContent.getBytes(StandardCharsets.UTF_8),
                    StandardOpenOption.TRUNCATE_EXISTING,
                    StandardOpenOption.WRITE
            );
            // 调用服务层保存
            tWarrantyService.updateBookJson(id,tWarranty.getJsonData(),updatedBy);

            return AjaxResult.success("保存成功");

        } catch (IOException e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 点新增按钮回调证书编码
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:add')")
    @Log(title = "证书编码", businessType = BusinessType.INSERT)
    @GetMapping("/getCode")
    public AjaxResult getCode()
    {
        return tWarrantyService.getCode();
    }

    /**
     * 修改list
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:edit')")
    @Log(title = "质保书列表", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TWarranty tWarranty)
    {
        tWarranty.setUpdatedAt(new Date());
        return toAjax(tWarrantyService.updateTWarranty(tWarranty));
    }

    /**
     * 删除list
     */
    @PreAuthorize("@ss.hasPermi('warranty:booklist:remove')")
    @Log(title = "质保书列表", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Integer[] ids)
    {
        return toAjax(tWarrantyService.deleteTWarrantyByIds(ids));
    }
}
